﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Resources;
using System.Xml;
using System.Xml.Linq;
using System.Threading;

namespace AirportApp.Data
{
    public class AirportViewModel : INotifyPropertyChanged
    {

        Database _db;
        public Database Db
        {
            get 
            {
                try
                {
                    var r = from a in _db.Airports
                            orderby a.Code
                            select a;
                    _allAirports = r.ToArray();
                    _filteredAirports = _allAirports;
                    UpdateNotify();
                }
                catch (Exception exc)
                {
                    Debug.WriteLine(exc.Message);
                    return null;
                }

                return _db; 
            }
        }

        Settings _settings;
        public AirportViewModel()
        {
            _settings = new Settings();

            if (_db == null)
            {
                _db = new Database();
            }

            if (!_db.DatabaseExists())
            {
                    _db.DeleteDatabase();
                _db.CreateDatabase();
            }

            if (_db.Airports.Count() == 0)
            {
                Load();
            }

            try
            {
                var r = from a in _db.Airports
                        orderby a.Code
                        select a;
                _allAirports = r.ToArray();
                _filteredAirports = _allAirports;
                UpdateNotify();
            }
            catch (Exception exc)
            {
                Debug.WriteLine(exc.Message);
            }

        }

        private void HandleError(Exception exception)
        {
            MessageBox.Show(exception.Message);
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #region Properties 

        public string[] Countries
        {
            get
            {
                if (Airports == null)
                {
                    return null;
                }
                var result = (from a in Airports
                             select a.Country).Distinct().OrderBy(a => a);
                return result.ToArray();
            }
        }

        private bool _isLoading;
        public bool IsLoading
        {
            get { return _isLoading; }
            set { _isLoading = value; OnPropertyChanged("IsLoading"); }
        }

        private AirportItem[] _allAirports;
        private AirportItem[] _filteredAirports;

        public AirportItem[] Airports
        {
            get 
            {
#if DEBUG
                if (DesignerProperties.IsInDesignTool)
                {
                    List<AirportItem> result = new List<AirportItem>();
                    //for (int a = 0; a < 10; a++)
                    //{
                        for (int i = 0; i < 3; i++)
                        {
                            AirportItem ap = new AirportItem();
                            ap.Name = "Airport " + i;
                            ap.Code = "ABC";
                            ap.CountryCode = "12";
                            ap.CountryShort = "DE";
                            ap.Country = "Germany";
                            result.Add(ap);
                        }
                        for (int i = 0; i < 3; i++)
                        {
                            AirportItem ap = new AirportItem();
                            ap.Name = "Airport " + i;
                            ap.Code = "XYZ";
                            ap.CountryCode = "12";
                            ap.CountryShort = "DE";
                            ap.Country = "Germany";
                            result.Add(ap);
                        }
                        for (int i = 0; i < 3; i++)
                        {
                            AirportItem ap = new AirportItem();
                            ap.Name = "Airport " + i;
                            ap.Code = "DEF";
                            ap.CountryCode = "12";
                            ap.CountryShort = "DE";
                            ap.Country = "England";
                            result.Add(ap);
                        }
                    //}
                    return result.ToArray();
                }
#endif
                return _filteredAirports;
                try
                {
                    var r = from a in Db.Airports
                            orderby a.Code
                            select a;
                    return r.ToArray();
                }
                catch (Exception exc)
                {
                    Debug.WriteLine(exc.Message);
                    return null;
                }
            }
        }

        public CountriesByName CountriesInGroups
        {
            get
            {
                return new CountriesByName(this.Countries);
            }
        }

        public AirportsByName AirportsInGroups
        {
            get
            {
                return new AirportsByName(_filteredAirports); // TODO: optimize
            }
        }

        #endregion

        public void Load()
        {
            // Clear();
            List<AirportItem> result = new List<AirportItem>();
            
            string url = "Data/airports.xml";
            XmlReader xr = XmlReader.Create(url);

            XDocument xdoc = XDocument.Load(xr);
            foreach (var airportXml in xdoc.Elements("ArrayOfAirport").Elements("Airport"))
            {
                AirportItem airport = new AirportItem();
                airport.Code = airportXml.Element("Code").Value;
                airport.Name = airportXml.Element("Name").Value;
                airport.CountryCode = airportXml.Element("CountryCode").Value;
                airport.Country = airportXml.Element("Country").Value;

                result.Add(airport);
            }

            foreach (var airport in result)
            {
                AirportItem ai = new AirportItem();
                ai.Code = airport.Code;
                ai.Name = airport.Name;
                ai.Country = airport.Country;
                //ai.CountryCode = airport.CountryCode.ToString();
                ai.CountryShort = airport.CountryShort;
                _db.Airports.InsertOnSubmit(ai);
                
            }
            _db.SubmitChanges();
            UpdateNotify();

            // Webservice Version
            /*
            DataServiceSoapClient _client = new DataServiceSoapClient();
            _client.GetAirportsCompleted += (s, e) =>
            {
                this.IsLoading = false;
                if (e.Error != null)
                {
                    HandleError(e.Error);
                    return;
                }
                foreach (var airport in e.Result)
                {
                    AirportItem ai = new AirportItem();
                    ai.Code = airport.Code;
                    ai.Name = airport.Name;
                    ai.Country = airport.Country;
                    //ai.CountryCode = airport.CountryCode.ToString();
                    ai.CountryShort = airport.CountryShort;
                    Db.Airports.InsertOnSubmit(ai);
                }
                Db.SubmitChanges();
                UpdateNotify();
            };
            _client.GetAirportsAsync();
             */
        }

        internal void Clear()
        {
            Db.DeleteDatabase();
            _db = null;
            UpdateNotify();
        }

        public void UpdateNotify()
        {
            OnPropertyChanged("Airports");
            OnPropertyChanged("Countries");
            OnPropertyChanged("AirportsInGroups");
            OnPropertyChanged("CountriesInGroups");
        }

        internal void FilterByAirport(string searchText)
        {
            _isFiltered = searchText.Length != 0;
            if (!_isFiltered)
            {
                _filteredAirports = _allAirports;
            }
            else
            {
                if (_settings.SearchAllText)
                {
                    var result = from a in Airports
                                 where a.Code.ToLower().Contains(searchText)
                                    || a.Country.ToLower().Contains(searchText)
                                    || a.Name.ToLower().Contains(searchText)
                                 select a;

                    _filteredAirports = result.ToArray();
                }
                else
                {
                    var result = from a in Airports
                                 where a.Code.ToLower().Contains(searchText)
                                 select a;

                    _filteredAirports = result.ToArray();
                }
            }
            UpdateNotify();
        }

        internal void FilterByCountry(string searchText)
        {
            _isFiltered = searchText.Length != 0;
            if (!_isFiltered)
            {
                _filteredAirports = _allAirports;
            }
            else
            {
                var resultC = from a in Airports
                              where a.Country.ToLower().Contains(searchText)
                              select a;
                _filteredAirports = resultC.ToArray();
            }
            UpdateNotify();
        }

        bool _isFiltered = false;
    }
}

 
